package org.lucava.boatskeeper.client.control;

import org.lucava.lib.client.control.Control;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.PopupPanel;
import java.util.List;
import org.lucava.lib.client.event.InitEvent;
import org.lucava.boatskeeper.client.event.user.CancelEditUserEvent;
import org.lucava.boatskeeper.client.event.user.DeleteUsersEvent;
import org.lucava.boatskeeper.client.event.user.EditSessionUserEvent;
import org.lucava.boatskeeper.client.event.user.EditUserEvent;
import org.lucava.boatskeeper.client.event.user.ListUsersEvent;
import org.lucava.boatskeeper.client.event.user.SaveUserEvent;
import org.lucava.boatskeeper.client.event.user.UserHandler;
import org.lucava.boatskeeper.client.service.RoleService;
import org.lucava.boatskeeper.client.service.RoleServiceAsync;
import org.lucava.boatskeeper.client.service.UserService;
import org.lucava.boatskeeper.client.service.UserServiceAsync;
import org.lucava.boatskeeper.client.view.UserEditView;
import org.lucava.boatskeeper.client.view.UserListView;
import org.lucava.boatskeeper.shared.dto.RoleDto;
import org.lucava.boatskeeper.shared.dto.UserDto;
import org.lucava.lib.client.session.SessionManager;

public class UserController extends Control implements UserHandler {

    private UserListView userListView;
    private UserEditView userEditView;
    private UserServiceAsync userService = GWT.create(UserService.class);
    private RoleServiceAsync roleService = GWT.create(RoleService.class);

    @Override
    public void onInitHandlers() {
        getEventBus().addHandler(SaveUserEvent.TYPE, UserController.this);
        getEventBus().addHandler(EditUserEvent.TYPE, UserController.this);
        getEventBus().addHandler(CancelEditUserEvent.TYPE, UserController.this);
        getEventBus().addHandler(DeleteUsersEvent.TYPE, UserController.this);
        getEventBus().addHandler(ListUsersEvent.TYPE, UserController.this);
        getEventBus().addHandler(EditSessionUserEvent.TYPE, UserController.this);
    }

    @Override
    public void onInit() {
        fetchUsers();

        userListView = new UserListView(getEventBus());

    }

    @Override
    public void onSaveUser(SaveUserEvent event) {
        if (userEditView.isValid()) {
            userService.saveUser(userEditView.getUser(), new AsyncCallback<Boolean>() {
                @Override
                public void onSuccess(Boolean result) {
                    getEventBus().fireEvent(new ListUsersEvent());
                }

                @Override
                public void onFailure(Throwable caught) {
                    Window.alert("Impossible de sauvegarder l'utilisateur \n ->" + caught.getLocalizedMessage());
                }
            });
        }
    }

    @Override
    public void onEditUser(EditUserEvent event) {
        userEditView = new UserEditView(getEventBus());
        editUser(event.getId());
    }

    private void editUser(Integer id) {
        if (id != null) {
            userService.getUser(id, new AsyncCallback<UserDto>() {
                @Override
                public void onSuccess(UserDto result) {
                    userEditView.setUser(result);
                    fetchRoles();
                }

                @Override
                public void onFailure(Throwable caught) {
                    Window.alert("Impossible de modifier l'utilisateur séléctionné \n ->" + caught.getLocalizedMessage());
                }
            });
        }

        assignView("content", userEditView);
    }

    @Override
    public void onCancelEditUser(CancelEditUserEvent event) {
        assignView("content", userListView);

    }

    @Override
    public void onDeleteUsers(DeleteUsersEvent event) {

        userService.removeUsers(userListView.getSelectedRows(), new AsyncCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                fetchUsers();
            }

            @Override
            public void onFailure(Throwable caught) {
                Window.alert("Impossible de supprimer les utilisateurs séléctionnés \n ->" + caught.getLocalizedMessage());
            }
        });

    }

    private void fetchUsers() {
        userService.getUsers(new AsyncCallback<List<UserDto>>() {
            @Override
            public void onSuccess(List<UserDto> result) {
                userListView.setUsers(result);
            }

            @Override
            public void onFailure(Throwable caught) {
                Window.alert("Impossible de récupérer les utilisateurs \n ->" + caught.getLocalizedMessage());
            }
        });
    }

    private void fetchRoles() {
        roleService.getRoles(new AsyncCallback<List<RoleDto>>() {
            @Override
            public void onSuccess(List<RoleDto> result) {
                userEditView.setRoles(result);
            }

            @Override
            public void onFailure(Throwable caught) {
                Window.alert("Impossible de supprimer les roles \n ->" + caught.getLocalizedMessage());
            }
        });
    }

    @Override
    public void onListUsers(ListUsersEvent aThis) {
        assignView("content", userListView);
    }

    @Override
    public void onEditSessionUser(EditSessionUserEvent aThis) {
        //TODO retrieve Id from session
        editUser(SessionManager.getInstance().getUser().getId());
    }
}
